home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / music / dsik_pas.zip / EXAM3.PAS < prev    next >
Pascal/Delphi Source File  |  1994-07-28  |  18KB  |  775 lines

  1. (*  play.pas  - DSIK Module Player v1.02
  2.  
  3.     Copyright 1993,94 Carlos Hasan
  4. *)
  5.  
  6. {_define UseTS}
  7.  
  8. program Play;
  9.  
  10. uses Dos,Sound,Load,TS;
  11.  
  12. const
  13.   (* Keyboard constants *)
  14.   kbEsc         = $001B;
  15.   kbSpace       = $0020;
  16.   kbPlus        = $002B;
  17.   kbMinus       = $002D;
  18.   kbLeft        = $4B00;
  19.   kbRight       = $4D00;
  20.  
  21. const
  22.   (* VGA 80x50 textmode constants *)
  23.   VideoSeg      = $B800;
  24.   VideoWidth    = 80;
  25.   VideoHeight   = 50;
  26.  
  27. const
  28.   (* VGA 8x8 Fonts *)
  29.   Fonts: array [1..8*13] of byte = (
  30.     $00,$e0,$e0,$e0,$e0,$e0,$e0,$00,
  31.     $00,$ee,$ee,$ee,$ee,$ee,$ee,$00,
  32.     $00,$00,$00,$00,$00,$00,$00,$ff,
  33.     $ff,$00,$00,$00,$00,$00,$00,$00,
  34.     $01,$01,$01,$01,$01,$01,$01,$01,
  35.     $80,$80,$80,$80,$80,$80,$80,$80,
  36.     $80,$00,$00,$00,$00,$00,$00,$00,
  37.     $00,$00,$00,$00,$00,$00,$00,$01,
  38.     $ff,$80,$80,$80,$80,$80,$80,$80,
  39.     $01,$01,$01,$01,$01,$01,$01,$ff,
  40.     $80,$c0,$e0,$f0,$f8,$fc,$fe,$ff,
  41.     $01,$03,$07,$0f,$1f,$3f,$7f,$ff,
  42.     $00,$1c,$3a,$3e,$3e,$1c,$00,$00
  43.   );
  44.  
  45. const
  46.   (* VGA RGB Palette *)
  47.   Palette : array [1..3*16] of byte = (
  48.     00,00,00,
  49.     06,10,22,
  50.     12,20,43,
  51.     20,32,63,
  52.     48,00,00,
  53.     00,44,00,
  54.     56,40,38,
  55.     63,63,63,
  56.     63,63,63,
  57.     63,63,63,
  58.     63,63,63,
  59.     00,50,63,
  60.     63,63,63,
  61.     63,63,63,
  62.     63,63,63,
  63.     50,50,63 );
  64.  
  65. type
  66.   TFrame = array [0..8] of word;
  67.  
  68. const
  69.   frame1: TFrame =
  70.     ( $2388,$028a,$208a,$2189,$2383,$2182,$2385,$2184,$2100 );
  71.  
  72.   frame2: TFrame =
  73.     ( $2289,$2288,$2287,$2186,$2382,$2183,$2384,$2185,$2100 );
  74.  
  75.   frame3: TFrame =
  76.     ( $2187,$2288,$2287,$2286,$2182,$2383,$2184,$2385,$0f00 );
  77.  
  78.   frame4: TFrame =
  79.     ( $128b,$128a,$218a,$218b,$2383,$2182,$2385,$2184,$2100 );
  80.  
  81.  
  82. (* Lowlevel VGA 80x50 TextMode routines *)
  83. procedure SetTextMode; assembler;
  84. asm
  85.         mov     ax,0003h
  86.         int     10h
  87. end;
  88.  
  89. procedure SetTweakedMode; assembler;
  90. asm
  91.         push    ax
  92.         push    bx
  93.         push    dx
  94.  
  95.         mov     ax,0003h                { set 80x25x16 textmode }
  96.         int     10h
  97.  
  98.         mov     ax,1112h                { set ROM 8x8 charset }
  99.         mov     bl,00h                  { in the block zero }
  100.         int     10h
  101.  
  102.         mov     dx,3C4h                 { sync reset while }
  103.         mov     ax,0100h                { setting misc output }
  104.         out     dx,ax
  105.  
  106.         mov     dx,3C2h                 { select the dot clock and }
  107.         mov     al,63h                  { Horiz scanning rate }
  108.         out     dx,al
  109.  
  110.         mov     dx,3C4h                 { select 8/9 dot clock }
  111.         mov     ax,0101h
  112.         out     dx,ax
  113.  
  114.         mov     dx,3C4h                 { undo reset }
  115.         mov     ax,0300h                { (restart sequencer) }
  116.         out     dx,ax
  117.  
  118.         mov     dx,3D4h                 { hide cursor }
  119.         mov     ax,100Ah
  120.         out     dx,ax
  121.         mov     al,0Bh
  122.         out     dx,ax
  123.  
  124.         pop     dx
  125.         pop     bx
  126.         pop     ax
  127. end;
  128.  
  129. procedure SetTextFont(var FontData; First,Count:word); assembler;
  130. asm
  131.         push    ax
  132.         push    bx
  133.         push    cx
  134.         push    dx
  135.         push    bp
  136.         push    es
  137.  
  138.         mov     ax,1100h                { load charset with reset }
  139.         mov     bx,0800h
  140.         mov     cx,[Count]
  141.         mov     dx,[First]
  142.         les     bp,[FontData]
  143.         int     10h
  144.  
  145.         pop     es
  146.         pop     bp
  147.         pop     dx
  148.         pop     cx
  149.         pop     bx
  150.         pop     ax
  151. end;
  152.  
  153. procedure SetPalette(var Palette; Count:word); assembler;
  154. const
  155.   Index : array [0..15] of byte = ( 0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63 );
  156. asm
  157.         push    ax
  158.         push    cx
  159.         push    dx
  160.         push    si
  161.         push    di
  162.         push    ds
  163.         push    es
  164.  
  165.         lea     di,[Index]
  166.         les     si,[Palette]
  167.         mov     cx,[Count]
  168.         mov     dx,3c8h
  169. @@0:    mov     al,[di]
  170.         out     dx,al
  171.         inc     dx
  172.         mov     al,[es:si]
  173.         out     dx,al
  174.         mov     al,[es:si+1]
  175.         out     dx,al
  176.         mov     al,[es:si+2]
  177.         out     dx,al
  178.         dec     dx
  179.         add     si,3
  180.         inc     di
  181.         loop    @@0
  182.  
  183.         pop     es
  184.         pop     ds
  185.         pop     di
  186.         pop     si
  187.         pop     dx
  188.         pop     cx
  189.         pop     ax
  190. end;
  191.  
  192. procedure DrawChar(X,Y:integer; C:char; Color:byte; Count:word); assembler;
  193. asm
  194.         push    di
  195.         push    es
  196.  
  197.         mov     ax,[Y]
  198.         mov     dx,VideoWidth
  199.         mul     dx
  200.         add     ax,[X]
  201.         add     ax,ax
  202.         mov     di,ax
  203.         mov     ax,VideoSeg
  204.         mov     es,ax
  205.         mov     ah,[Color]
  206.         mov     al,[C]
  207.         mov     cx,[Count]
  208.         cld
  209.         rep     stosw
  210.  
  211.         pop     es
  212.         pop     di
  213. end;
  214.  
  215. procedure DrawText(X,Y:integer; Text:PChar; Color:Byte; Max:word); assembler;
  216. asm
  217.         push    si
  218.         push    di
  219.         push    ds
  220.         push    es
  221.  
  222.         mov     ax,[Y]
  223.         mov     dx,VideoWidth
  224.         mul     dx
  225.         add     ax,[X]
  226.         add     ax,ax
  227.         mov     di,ax
  228.         mov     ax,VideoSeg
  229.         mov     es,ax
  230.         mov     ah,[Color]
  231.         mov     cx,[Max]
  232.         lds     si,[Text]
  233.  
  234. @0:     mov     al,[ds:si]
  235.         test    al,al
  236.         je      @1
  237.         mov     [es:di],ax
  238.         add     di,2
  239.         inc     si
  240.         dec     cx
  241.         jg      @0
  242.  
  243. @1:     mov     al,20h
  244.         test    cx,cx
  245.         jle     @3
  246. @2:     mov     [es:di],ax
  247.         add     di,2
  248.         loop    @2
  249.  
  250. @3:     pop     es
  251.         pop     ds
  252.         pop     di
  253.         pop     si
  254. end;
  255.  
  256. procedure DrawNum(X,Y:integer; Num:word; Color:byte); assembler;
  257. asm
  258.         push    si
  259.         push    di
  260.         push    es
  261.  
  262.         mov     ax,[Y]
  263.         mov     dx,VideoWidth
  264.         mul     dx
  265.         add     ax,[X]
  266.         add     ax,ax
  267.         mov     di,ax
  268.         mov     ax,VideoSeg
  269.         mov     es,ax
  270.         mov     bh,[Color]
  271.         mov     ax,[Num]
  272.         aam
  273.         or      al,30h
  274.         mov     bl,al
  275.         mov     [es:di+4],bx
  276.         mov     al,ah
  277.         aam
  278.         or      al,30h
  279.         mov     bl,al
  280.         mov     [es:di+2],bx
  281.         mov     al,ah
  282.         aam
  283.         or      al,30h
  284.         mov     bl,al
  285.         mov     [es:di],bx
  286.  
  287.         pop     es
  288.         pop     di
  289.         pop     si
  290. end;
  291.  
  292. procedure DrawNum2(X,Y:integer; Num:word; Color:byte); assembler;
  293. asm
  294.         push    si
  295.         push    di
  296.         push    es
  297.  
  298.         mov     ax,[Y]
  299.         mov     dx,VideoWidth
  300.         mul     dx
  301.         add     ax,[X]
  302.         add     ax,ax
  303.         mov     di,ax
  304.         mov     ax,VideoSeg
  305.         mov     es,ax
  306.         mov     bh,[Color]
  307.         mov     ax,[Num]
  308.         aam
  309.         or      al,30h
  310.         mov     bl,al
  311.         mov     [es:di+2],bx
  312.         mov     al,ah
  313.         aam
  314.         or      al,30h
  315.         mov     bl,al
  316.         mov     [es:di],bx
  317.  
  318.         pop     es
  319.         pop     di
  320.         pop     si
  321. end;
  322.  
  323. procedure DrawNote(X,Y:integer; Note:word); assembler;
  324. const
  325.   Notes: array [1..3*13] of char = '∙∙∙C-?C#?D-?D#?E-?F-?F#?G-?G#?A-?A#?B-?';
  326. asm
  327.         push    si
  328.         push    di
  329.         push    es
  330.  
  331.         mov     ax,[Y]
  332.         mov     dx,VideoWidth
  333.         mul     dx
  334.         add     ax,[X]
  335.         add     ax,ax
  336.         mov     di,ax
  337.         mov     ax,VideoSeg
  338.         mov     es,ax
  339.         mov     cx,3
  340.         lea     si,[Notes]
  341.         mov     ax,[Note]
  342.         dec     ax
  343.         jl      @0
  344.         xor     dx,dx
  345.         mov     bx,12
  346.         div     bx
  347.         add     si,dx
  348.         add     dx,dx
  349.         add     si,dx
  350.         add     si,3
  351.         or      al,30h
  352.         mov     [ds:si+2],al
  353. @0:     mov     al,[ds:si]
  354.         mov     [es:di],al
  355.         add     di,2
  356.         inc     si
  357.         loop    @0
  358.  
  359.         pop     es
  360.         pop     di
  361.         pop     si
  362. end;
  363.  
  364. procedure DrawFrame(XLeft,YTop,XRight,YBottom:Integer; const Frame:TFrame); assembler;
  365. asm
  366.         push    si
  367.         push    di
  368.         push    ds
  369.         push    es
  370.  
  371.         lds     si,[Frame]
  372.         mov     ax,VideoSeg
  373.         mov     es,ax
  374.         mov     ax,[YTop]
  375.         mov     dx,VideoWidth
  376.         mul     dx
  377.         add     ax,[XLeft]
  378.         add     ax,ax
  379.         mov     di,ax
  380.         mov     bx,[XRight]
  381.         sub     bx,[XLeft]
  382.         dec     bx
  383.         jl      @0
  384.         mov     dx,[YBottom]
  385.         sub     dx,[YTop]
  386.         dec     dx
  387.         jl      @0
  388.         cld
  389.         push    di
  390.         mov     ax,[si+2*0]
  391.         stosw
  392.         mov     ax,[si+2*4]
  393.         mov     cx,bx
  394.         rep     stosw
  395.         mov     ax,[si+2*1]
  396.         stosw
  397.         pop     di
  398.         add     di,2*VideoWidth
  399. @1:     push    di
  400.         mov     ax,[si+2*6]
  401.         stosw
  402.         mov     ax,[si+2*8]
  403.         mov     cx,bx
  404.         rep     stosw
  405.         mov     ax,[si+2*7]
  406.         stosw
  407.         pop     di
  408.         add     di,2*VideoWidth
  409.         dec     dx
  410.         jne     @1
  411.         mov     ax,[si+2*2]
  412.         stosw
  413.         mov     ax,[si+2*5]
  414.         mov     cx,bx
  415.         rep     stosw
  416.         mov     ax,[si+2*3]
  417.         stosw
  418.  
  419. @0:     pop     es
  420.         pop     ds
  421.         pop     di
  422.         pop     si
  423. end;
  424.  
  425. procedure DrawMeter(X,Y:integer; Count:word); assembler;
  426. asm
  427.         push    di
  428.         push    es
  429.  
  430.         mov     ax,VideoSeg
  431.         mov     es,ax
  432.         mov     ax,[Y]
  433.         mov     dx,VideoWidth
  434.         mul     dx
  435.         add     ax,[X]
  436.         add     ax,ax
  437.         mov     di,ax
  438.         mov     dx,[Count]
  439.         cmp     dx,32
  440.         jle     @0
  441.         mov     dx,32
  442. @0:     mov     cx,dx
  443.         shr     cx,1
  444.         cld
  445.         mov     ax,0B81h
  446.         rep     stosw
  447.         mov     cx,dx
  448.         test    cx,1
  449.         je      @1
  450.         inc     cx
  451.         mov     ax,0B80h
  452.         stosw
  453. @1:     neg     cx
  454.         add     cx,32
  455.         shr     cx,1
  456.         xor     ax,ax
  457.         rep     stosw
  458.  
  459.         pop     es
  460.         pop     di
  461. end;
  462.  
  463. procedure DrawBar(X,Y:integer; Count:word); assembler;
  464. asm
  465.         push    di
  466.         push    es
  467.  
  468.         mov     ax,VideoSeg
  469.         mov     es,ax
  470.         mov     ax,[Y]
  471.         mov     dx,VideoWidth
  472.         mul     dx
  473.         add     ax,[X]
  474.         add     ax,ax
  475.         mov     di,ax
  476.  
  477.         mov     dx,[Count]
  478.         cmp     dx,24
  479.         jle     @0
  480.         mov     dx,24
  481. @0:     mov     cx,dx
  482.         shr     cx,1
  483.         cld
  484.         mov     ax,0681h
  485.         rep     stosw
  486.         mov     cx,dx
  487.         test    cx,1
  488.         je      @1
  489.         inc     cx
  490.         mov     ax,0680h
  491.         stosw
  492.  
  493. @1:     mov     dx,[Count]
  494.         cmp     dx,32
  495.         jle     @2
  496.         mov     dx,32
  497. @2:     mov     cx,dx
  498.         cmp     cx,24
  499.         jle     @3
  500.         sub     cx,24
  501.         shr     cx,1
  502.         cld
  503.         mov     ax,0481h
  504.         rep     stosw
  505.         mov     cx,dx
  506.         test    cx,1
  507.         je      @3
  508.         inc     cx
  509.         mov     ax,0480h
  510.         stosw
  511.  
  512. @3:     neg     cx
  513.         add     cx,32
  514.         shr     cx,1
  515.         xor     ax,ax
  516.         rep     stosw
  517.  
  518.         pop     es
  519.         pop     di
  520. end;
  521.  
  522. (* Lowlevel Keyboard routines *)
  523. function Keypressed: boolean; assembler;
  524. asm
  525.         mov     ah,01h
  526.         int     16h
  527.         mov     ax,0
  528.         je      @0
  529.         mov     ax,1
  530. @0:
  531. end;
  532.  
  533. function ReadKey: word; assembler;
  534. asm
  535.         mov     ah,00h
  536.         int     16h
  537.         test    al,al
  538.         je      @0
  539.         xor     ah,ah
  540. @0:
  541. end;
  542.  
  543. var
  544.     Path   : PathStr;
  545.     Dir    : DirStr;
  546.     Name   : NameStr;
  547.     Ext    : ExtStr;
  548.     Card   : DSMCard;
  549.     Module : PDSM;
  550.     Music  : PDSMMusicInfo;
  551.     Error,Volume,Key,I,J,N : Integer;
  552. begin
  553.     writeln('DSIK Module Player V1.02  Copyright 1993,94 Carlos Hasan');
  554.  
  555.     (* Get Command Line Parameters *)
  556.     if ParamCount < 1 then begin
  557.         writeln('Usage: PLAY file[.dsm]');
  558.         exit;
  559.     end;
  560.     fsplit(ParamStr(1),Dir,Name,Ext);
  561.     if Ext = '' then Ext := '.DSM';
  562.     Path := Dir + Name + Ext;
  563.  
  564.     (* Sound Card configuration *)
  565.     if DSMLoadSetup(Card) then begin
  566.         writeln('Please run SETUP.EXE to configure.');
  567.         exit;
  568.     end;
  569.  
  570.     (* Initialize the Sound System *)
  571.     if DSMInit(Card) then begin
  572.         writeln('Error Initializing the Sound System.');
  573.         exit;
  574.     end;
  575.  
  576.     (* Load Module File *)
  577.     Module := DSMLoad(Path,0);
  578.     if Module = nil then begin
  579.         case (DSMStatus) of
  580.             ERR_NORAM:  writeln('Not enough system memory.');
  581.             ERR_NODRAM: writeln('Not enough card memory.');
  582.             ERR_NOFILE: writeln('File not found (',Path,').');
  583.             ERR_FORMAT: writeln('Invalid file format.');
  584.             ERR_ACCESS: writeln('File damaged.');
  585.         end;
  586.         DSMDone;
  587.         exit;
  588.     end;
  589.  
  590.     (* Setup Text Screen *)
  591.     SetTweakedMode;
  592.     SetPalette(Palette,sizeof(Palette) div 3);
  593.     SetTextFont(Fonts,$80,sizeof(Fonts) shr 3);
  594.  
  595.     (* Draw Panel *)
  596.     DrawFrame(1,0,78,49,frame1);
  597.     DrawChar(4,1,#130,$21,72);
  598.     DrawChar(4,2,#131,$23,72);
  599.     DrawChar(4,4,#130,$21,72);
  600.     DrawChar(4,5,#131,$23,72);
  601.     DrawText(5,3,'DSIK Module Player Version 1.02     Copyright (C) 1993,94 Carlos Hasan',$2b,70);
  602.  
  603.     (* Draw InfoBox *)
  604.     DrawChar(10,6,#135,$21,1);
  605.     DrawChar(11,6,#130,$21,39);
  606.  
  607.     DrawChar(10,7,#132,$21,1);
  608.     DrawChar(11,7,#032,$05,39);
  609.     DrawChar(50,7,#138,$20,1);
  610.  
  611.     DrawChar(10,8,#132,$21,1);
  612.     DrawChar(11,8,#032,$05,8);
  613.     DrawChar(15,8,#047,$05,1);
  614.     DrawChar(19,8,#132,$03,1);
  615.     DrawChar(20,8,#131,$23,25);
  616.     DrawChar(45,8,#138,$02,1);
  617.     DrawChar(46,8,#032,$05,4);
  618.     DrawChar(50,8,#132,$03,1);
  619.  
  620.     DrawChar(10,9,#132,$21,1);
  621.     DrawChar(11,9,#032,$05,3);
  622.     DrawChar(14,9,#132,$03,1);
  623.     DrawChar(15,9,#131,$23,5);
  624.     DrawChar(45,9,#132,$21,1);
  625.     DrawChar(46,9,#032,$05,4);
  626.     DrawChar(50,9,#132,$03,1);
  627.  
  628.     DrawChar(11,10,#131,$23,4);
  629.     DrawChar(46,10,#131,$23,5);
  630.  
  631.     DrawFrame(59,6,76,9,frame3);
  632.  
  633.     DrawText(5,7,'Song:',$21,5);
  634.     DrawText(4,8,'Order:',$21,6);
  635.     DrawText(6,9,'Row:',$21,4);
  636.     DrawText(37,9,'Pattern:',$21,8);
  637.     DrawText(53,7,'Played',$21,6);
  638.     DrawText(53,8,'Volume',$21,6);
  639.  
  640.     (* Put SongName *)
  641.     DrawText(12,7,Module^.Song.SongName,$05,38);
  642.     N := Module^.Song.NumChannels;
  643.  
  644.     (* Draw TrackBox *)
  645.     DrawFrame(03,11,76,16+N,frame3);
  646.     DrawFrame(04,12,75,15+N,frame4);
  647.  
  648.     DrawFrame(11,13,23,14+N,frame3);
  649.     DrawFrame(24,13,54,14+N,frame3);
  650.     DrawFrame(55,13,72,14+N,frame3);
  651.  
  652.     DrawFrame(06,13,07,14+N,frame2);
  653.     DrawFrame(10,13,11,14+N,frame2);
  654.  
  655.     for I := 1 to N do begin
  656.         DrawNum2(8,13+I,I,$21);
  657.     end;
  658.  
  659.     (* Draw SamplesBox *)
  660.     J := 2*(28-N);
  661.     if J > Module^.Song.NumSamples then J := Module^.Song.NumSamples;
  662.     J := succ(J) shr 1;
  663.  
  664.     DrawFrame(03,17+N,76,20+N+J,frame2);
  665.     DrawFrame(04,18+N,75,19+N+J,frame3);
  666.  
  667.     for I := 0 to pred(J) do begin
  668.         DrawNum2(06,19+N+I,I+1,$0f);
  669.         DrawNum2(41,19+N+I,I+J+1,$0f);
  670.         if Module^.Inst[I] <> nil then
  671.             DrawText(09,19+N+I,Module^.Inst[I]^.SampleName,$0b,28);
  672.         if Module^.Inst[I+J] <> nil then
  673.             DrawText(44,19+N+I,Module^.Inst[I+J]^.SampleName,$0b,28);
  674.     end;
  675.  
  676.     (* Start Playing Music *)
  677.     DSMSetupVoices(Module^.Song.NumChannels,Module^.Song.MasterVolume);
  678.     DSMPlayMusic(Module);
  679.     Music := DSMGetMusicInfo;
  680.     Volume := 255;
  681.  
  682.     (* Setup the timer service *)
  683. {$ifdef UseTS}
  684.     TSInit;
  685.     TSSetRate(70);
  686.     TSSetRoutine(DSMPoll);
  687. {$endif}
  688.  
  689.     Key := 0;
  690.     while Key <> kbEsc do begin
  691.  
  692.         (* Poll Music System *)
  693. {$ifndef UseTS}
  694.         DSMPoll;
  695. {$endif}
  696.  
  697.         (* Update InfoBox *)
  698.         if Music^.BreakFlag = PB_NONE then begin
  699.             DrawNum(12,8,Music^.OrderPosition,$05);
  700.             DrawNum(16,8,Music^.OrderLength,$05);
  701.             DrawNum2(12,9,Music^.PatternRow,$05);
  702.             DrawNum(47,9,Music^.PatternNumber,$05);
  703.             DrawMeter(60,7,(32*Music^.OrderPosition+(Music^.PatternRow shr 1)) div Music^.OrderLength);
  704.             DrawMeter(60,8,Volume shr 3);
  705.         end;
  706.  
  707.         (* Update TrackBox *)
  708.         for i := 0 to Pred(N) do with Music^.Tracks[i] do begin
  709.             if Lo(NoteEvent) <> 0 then DrawChar(5,14+i,#140,$25,1)
  710.             else DrawChar(5,14+i,#140,$21,1);
  711.             DrawNote(13,14+i,Note);
  712.             DrawNum2(17,14+i,Sample,$0f);
  713.             DrawNum2(20,14+i,Volume,$0f);
  714.             if Sample <> 0 then
  715.                 DrawText(26,14+i,Module^.Inst[Pred(Sample)]^.SampleName,$0f,28);
  716.             DrawBar(56,14+i,EQBar shr 1);
  717.         end;
  718.  
  719.         (* Dispatch Keyboard *)
  720.         if keypressed then begin
  721.             Key := Readkey;
  722.             case Key of
  723.                 kbPlus:
  724.                 if (Volume <= 247) then begin
  725.                     inc(Volume,8);
  726.                     DSMSetMusicVolume(Volume);
  727.                 end;
  728.  
  729.                 kbMinus:
  730.                 if (Volume >= 8) then begin
  731.                     dec(Volume,8);
  732.                     DSMSetMusicVolume(Volume);
  733.                 end;
  734.  
  735.                 kbSpace:
  736.                 case (DSMGetMusicStatus) of
  737.                     PS_PLAYING: DSMStopMusic;
  738.                     PS_STOPPED: DSMPlayMusic(Module);
  739.                 end;
  740.  
  741.                 kbLeft:
  742.                 begin
  743.                     dec(Music^.OrderPosition);
  744.                     Music^.PatternRow := 0;
  745.                     Music^.BreakFlag := PB_JUMP;
  746.                 end;
  747.  
  748.                 kbRight:
  749.                 begin
  750.                     inc(Music^.OrderPosition);
  751.                     Music^.PatternRow := 0;
  752.                     Music^.BreakFlag := PB_JUMP;
  753.                 end;
  754.             end;
  755.         end;
  756.     end;
  757.  
  758.     (* Done timer service and restore time *)
  759. {$ifdef UseTS}
  760.     TSDone;
  761.     TSRestoreTime;
  762. {$endif}
  763.  
  764.     (* Stop Playing and Free Module *)
  765.     DSMStopMusic;
  766.     DSMFree(Module);
  767.  
  768.     (* Shutdown Music System *)
  769.     DSMDone;
  770.  
  771.     (* Clear the Text Screen *)
  772.     SetTextMode;
  773. end.
  774.  
  775.